package xcmg.device.service.agentPlan;

import com.github.pagehelper.PageInfo;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import xcmg.device.dao.entity.DataDictionaryDO;
import xcmg.device.dao.entity.PriMaterialsDO;
import xcmg.device.dao.entity.agentPlan.AgentPlanDO;
import xcmg.device.dao.entity.agentPlan.AgentPlanDetailDO;
import xcmg.device.dao.entity.company.CompanyInfoDO;
import xcmg.device.dao.entity.safetyStock.MaterialsSafetyStock;
import xcmg.device.dao.mapper.CompanyInfoMapper;
import xcmg.device.dao.mapper.DataDictionaryMapper;
import xcmg.device.dao.mapper.PriMaterialsMapper;
import xcmg.device.dao.mapper.PurchaseRequestDetailMapper;
import xcmg.device.dao.mapper.agentPlan.AgentPlanDetailMapper;
import xcmg.device.dao.mapper.agentPlan.AgentPlanMapper;
import xcmg.device.dao.mapper.announcement.BasicAnnouncementAuthMapper;
import xcmg.device.dao.mapper.safetyStock.MaterialsSafetyStockMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseInventoryMapper;
import xcmg.device.infra.DateUtil;
import xcmg.device.infra.ErrorCode;
import xcmg.device.infra.ExportUtil;
import xcmg.device.infra.StringUtil;
import xcmg.device.infra.enums.AgentPlanStatusEnum;
import xcmg.device.infra.enums.BillDesc;
import xcmg.device.service.GenDocumentService;
import xcmg.device.service.vo.FunctionResult;
import xcmg.device.service.vo.agentPlan.AgentPlanAddVO;
import xcmg.device.service.vo.agentPlan.AgentPlanDetailVO;
import xcmg.device.service.vo.agentPlan.AgentPlanSelectVO;
import xcmg.device.service.vo.agentPlan.AgentPlanVO;
import xcmg.device.service.warehouse.CommonService;
import xcmg.device.util.DecimalUtil;
import yb.ecp.fast.dto.UserCacheDTO;
import yb.ecp.fast.feign.FastGenClient;
import yb.ecp.fast.infra.infra.ActionResult;
import yb.ecp.fast.infra.infra.PageCommonVO;
import yb.ecp.fast.infra.infra.SearchCommonVO;
import yb.ecp.fast.infra.util.ListUtil;
import yb.ecp.fast.infra.util.PageHelperPlus;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author wangyong
 */
@Service
public class AgentPlanService {


    @Autowired
    private AgentPlanMapper agentPlanMapper;

  @Autowired
  private AgentPlanDetailMapper agentPlanDetailMapper;

  @Autowired
  private CommonService commonService;

  @Autowired
  private FastGenClient fastGenClient;

  @Autowired
  private GenDocumentService genDocumentService;

  @Autowired
  private PriMaterialsMapper priMaterialsMapper;

  @Autowired
  private BasicAnnouncementAuthMapper basicAnnouncementAuthMapper;


  @Autowired
  private HttpServletResponse response;

  @Autowired
  private DataDictionaryMapper dataDictionaryMapper;

  @Autowired
  private CompanyInfoMapper companyInfoMapper;

  @Autowired
  private MaterialsSafetyStockMapper materialsSafetyStockMapper;

  @Autowired
  private PurchaseRequestDetailMapper purchaseRequestDetailMapper;

  @Autowired
  private WarehouseInventoryMapper warehouseInventoryMapper;

  /**
   * 总部部门父级部门ID为0
   */
  private static final String HEADQUARTERS_PARENT_DEPT_ID = "0";

  /**
   * 是否删除。0否1是
   */
  private static final Short DELETE_FLAG_NO = 0, DELETE_FLAG_YES = 1;

  /**
   * 采购计划类型。0门店采购计划，1汇总采购计划
   */
  private static final Integer PLAN_TYPE_STORE = 0, PLAN_TYPE_SUMMARY = 1;

  /**
   * 是否生成采购订单。0否，1是
   */
  private static final Short GEN_PUR_FLAG_NO = 0, GEN_PUR_FLAG_YES = 1;


  /**
   * 代理商采购计划类型CODE
   */
  private static final String AGENT_PLAN_PARAM_CODE = "DLSCGJH";

  /**
   * 采购计划类型：1紧急，2补库
   */
  private static final Integer AGENT_PLAN_TYPE_ID_BK = 2;


  @Transactional(rollbackFor = Exception.class)
  public void save(AgentPlanAddVO addVO, String userId, String orgId, Integer afterStatus) throws Exception {
    AgentPlanVO planVO = addVO.getHeaderInfo();
    UserCacheDTO userInfo = commonService.getUserInfo(userId);
    Assert.notNull(userInfo,"userInfo is null");
    String planNo = genDocumentService.genDocumentNo(BillDesc.AgentPlan, orgId);
    AgentPlanDO planDO = new AgentPlanDO();
    ActionResult<String> textResult = fastGenClient.textGuid();
    String planId = textResult.getValue();
    planDO.setId(planId);
    planDO.setPlanNo(planNo);
    planDO.setTypeId(planVO.getTypeId());
    planDO.setTypeDesc(getPurchaseDesc(planVO.getTypeId()));
    planDO.setPlanType(planVO.getPlanType());
    if (planVO.isSummaryPlan()) {
      planDO.setGenPurFlag(GEN_PUR_FLAG_NO);
    }
    planDO.setStatus(afterStatus);
    planDO.setDeleteFlag(DELETE_FLAG_NO);
    planDO.setRemark(planVO.getRemark());
    planDO.setOrgId(orgId);
    planDO.setDeptId(userInfo.getDeptId());

    if (null == userInfo.getDeptName() && HEADQUARTERS_PARENT_DEPT_ID.equals(userInfo.getDeptId())) {
      CompanyInfoDO companyInfoDO = companyInfoMapper.item(orgId);
      if (null == companyInfoDO) {
        throw new Exception("未查询到相关公司：" + orgId);
      }
      planDO.setDeptName(companyInfoDO.getCompanyName());
    } else {
      planDO.setDeptName(userInfo.getDeptName());
    }
    planDO.setCreateId(userInfo.getUserId());
    planDO.setCreateName(userInfo.getName());
    planDO.setCreateTime(new Date());
    agentPlanMapper.insert(planDO);
    saveDetails(addVO.getDetailList(), planId, planNo, orgId);

    // 如果新增的是汇总采购计划，则更新对应的被汇总的采购计划
    if (planVO.isSummaryPlan()) {
      updateSourcePlan(addVO.getSourcePlanNos(), planNo, orgId);
    }
  }

  private void updateSourcePlan(List<String> sourcePlanNos, String mergePlanNo, String orgId) throws Exception {
    if (CollectionUtils.isEmpty(sourcePlanNos)) {
      throw new Exception("汇总来源单号不能为空");
    }
    for (String sourcePlanNo : sourcePlanNos) {
      AgentPlanDO planDO = agentPlanMapper.getByPlanNo(sourcePlanNo, orgId);
      planDO.setMergeNo(mergePlanNo);
      planDO.setStatus(AgentPlanStatusEnum.SUMMARY.getStatus());
      agentPlanMapper.update(planDO);
    }
  }

  private void saveDetails(List<AgentPlanDetailVO> detailVOS, String planId, String planNo,
      String orgId)
      throws Exception {

    AgentPlanDetailDO detailDO;
    for (AgentPlanDetailVO detailVO : detailVOS) {
      detailDO = new AgentPlanDetailDO();
      ActionResult<String> textResult = fastGenClient.textGuid();
      PriMaterialsDO materialsDO = priMaterialsMapper.itemByNo(detailVO.getMaterialsNo(), orgId);
      if (null == materialsDO) {
        throw new Exception("零件不存在。materialsNo : " + detailVO.getMaterialsNo());
      }
      detailDO.setId(textResult.getValue());
      detailDO.setPlanId(planId);
      detailDO.setPlanNo(planNo);
      detailDO.setMaterialsNo(detailVO.getMaterialsNo());
      detailDO.setMaterialsDes(materialsDO.getMaterialsDes());
      detailDO.setMaterialsType(materialsDO.getMaterialsType());
      detailDO.setUnit(materialsDO.getUnit());
      detailDO.setPrice(materialsDO.getPrice());
      detailDO.setQty(detailVO.getQty());
      detailDO.setAmount(detailVO.getQty().multiply(materialsDO.getPrice()));
      if (null == detailVO.getAdjustQty() || BigDecimal.ZERO.compareTo(detailVO.getAdjustQty()) == 0) {
        detailDO.setAdjustQty(detailDO.getQty());
        detailDO.setAdjustAmount(detailDO.getAmount());
      } else {
        detailDO.setAdjustQty(detailVO.getAdjustQty());
        detailDO.setAdjustAmount(detailVO.getAdjustQty().multiply(materialsDO.getPrice()));
      }
      agentPlanDetailMapper.insert(detailDO);
    }
  }

  public AgentPlanAddVO item(String id) {
    AgentPlanAddVO addVO = new AgentPlanAddVO();
    AgentPlanDO agentPlanDO = agentPlanMapper.getById(id);
    AgentPlanVO planVO = new AgentPlanVO();
    BeanUtils.copyProperties(agentPlanDO, planVO);
    planVO.setStatusDesc(AgentPlanStatusEnum.getByStatus(agentPlanDO.getStatus()).getDesc());
    List<AgentPlanDetailDO> detailDOS = agentPlanDetailMapper.listByPlanId(id);
    List<AgentPlanDetailVO> detailVOS = new ArrayList<>();
    AgentPlanDetailVO detailVO;
    for (AgentPlanDetailDO detailDO : detailDOS) {
      detailVO = new AgentPlanDetailVO();
      BeanUtils.copyProperties(detailDO, detailVO);
      detailVO = resetPrice4Show(detailVO);
      detailVOS.add(detailVO);
    }
    addVO.setHeaderInfo(planVO);
    addVO.setDetailList(detailVOS);
    return addVO;
  }

  /**
   * 价格显示除以100
   *
   * @param detailVO
   * @return
   */
  private AgentPlanDetailVO resetPrice4Show(AgentPlanDetailVO detailVO) {
    detailVO.setPrice(DecimalUtil.roundDecimal4Output(detailVO.getPrice()));
    detailVO.setAmount(DecimalUtil.roundDecimal4Output(detailVO.getAmount()));
    detailVO.setAdjustAmount(DecimalUtil.roundDecimal4Output(detailVO.getAdjustAmount()));
    return detailVO;
  }

  public PageCommonVO list(SearchCommonVO<AgentPlanVO> condition, Integer planType) {
    AgentPlanVO agentPlanVO = resetSearchCondition(condition.getFilters(), planType);
    PageCommonVO<AgentPlanVO> pageCommonVO = new PageCommonVO();
      PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize());
    List<AgentPlanDO> doList = agentPlanMapper.list(agentPlanVO);
    List<AgentPlanVO> voList = new ArrayList<>();
    AgentPlanVO planVO;
    for (AgentPlanDO planDO : doList) {
      planVO = new AgentPlanVO();
      BeanUtils.copyProperties(planDO, planVO);
      planVO.setStatusDesc(AgentPlanStatusEnum.getByStatus(planDO.getStatus()).getDesc());
      voList.add(planVO);
    }
    pageCommonVO.setPageInfo(new PageInfo(doList));
    pageCommonVO.setPageInfoList(voList);
    return pageCommonVO;
  }

  /**
   * 重置搜索条件
   *
   * @param agentPlanVO
   * @param planType
   * @return
   */
  private AgentPlanVO resetSearchCondition(AgentPlanVO agentPlanVO, Integer planType) {
    agentPlanVO.setPlanType(planType);
    if (null != agentPlanVO.getStartCreateTime()) {
      agentPlanVO.setStartCreateTime(DateUtil.getStartTimeOfDay(agentPlanVO.getStartCreateTime()));
    }
    if (null != agentPlanVO.getEndCreateTime()) {
      agentPlanVO.setEndCreateTime(DateUtil.getEndTimeOfDay(agentPlanVO.getEndCreateTime()));
    }
    if (null != agentPlanVO.getStartAuditTime()) {
      agentPlanVO.setStartAuditTime(DateUtil.getStartTimeOfDay(agentPlanVO.getStartAuditTime()));
    }
    if (null != agentPlanVO.getEndAuditTime()) {
      agentPlanVO.setEndAuditTime(DateUtil.getEndTimeOfDay(agentPlanVO.getEndAuditTime()));
    }
    return agentPlanVO;
  }

  /**
   * 审核
   *
   * @param agentPlanVO
   * @param userId
   * @param afterStatus 审核后的状态
   * @throws Exception
   */
  @Transactional(rollbackFor = Exception.class)
  public void audit(AgentPlanVO agentPlanVO, String userId, Integer afterStatus) throws Exception {
    UserCacheDTO userInfo = commonService.getUserInfo(userId);
    if (!isHeadquartersUser(userInfo.getDeptId())) {
      throw new Exception("仅总部人员可审核");
    }
    AgentPlanDO planDO = agentPlanMapper.getById(agentPlanVO.getId());

    if (!AgentPlanStatusEnum.getByStatus(planDO.getStatus()).isCanAudit()) {
      throw new Exception("当前状态不可审核");
    }
    planDO.setId(agentPlanVO.getId());
    planDO.setStatus(afterStatus);
    planDO.setReturnAdvice(agentPlanVO.getReturnAdvice());
    planDO.setAuditId(userId);
    planDO.setAuditName(userInfo.getName());
    planDO.setAuditTime(new Date());
    agentPlanMapper.update(planDO);
  }

  /**
   * 判断用户是否是代理商总部人员
   *
   * @param userDeptId
   * @return
   */
  private boolean isHeadquartersUser(String userDeptId) {
    return HEADQUARTERS_PARENT_DEPT_ID.equals(userDeptId) ||
        HEADQUARTERS_PARENT_DEPT_ID.equals(basicAnnouncementAuthMapper.getParentDeptId(userDeptId));
  }

  @Transactional(rollbackFor = Exception.class)
  public void update(AgentPlanAddVO addVO, String userId, String orgId, Integer afterStatus) throws Exception {
    AgentPlanVO planVO = addVO.getHeaderInfo();
    UserCacheDTO userInfo = commonService.getUserInfo(userId);
    Assert.notNull(userInfo,"userInfo is null");
    AgentPlanDO planDO = agentPlanMapper.getById(planVO.getId());
    if (!planDO.getDeptId().equals(userInfo.getDeptId())) {
      throw new Exception("仅门店内部人员可修改");
    }
    if (!AgentPlanStatusEnum.getByStatus(planDO.getStatus()).isCanUpdate()) {
      throw new Exception("当前状态不可修改");
    }

    planDO.setTypeId(planVO.getTypeId());
    planDO.setTypeDesc(getPurchaseDesc(planVO.getTypeId()));
    planDO.setStatus(afterStatus);
    planDO.setRemark(planVO.getRemark());
    planDO.setUpdateId(userId);
    planDO.setUpdateName(userInfo.getName());
    planDO.setUpdateTime(new Date());
    agentPlanMapper.update(planDO);
    updatePlanMaterials(addVO.getDetailList(), planVO.getId(), planVO.getPlanNo(), orgId);
  }

  private String getPurchaseDesc(Integer typeId) {
    DataDictionaryDO dictionaryDO = dataDictionaryMapper.itemByCode(AGENT_PLAN_PARAM_CODE, String.valueOf(typeId));
    if (null == dictionaryDO) {
      return StringUtils.EMPTY;
    }
    return dictionaryDO.getName();
  }

  /**
   * 更新采购计划的零件
   *
   * @param detailVOS
   * @param planId
   * @param planNo
   * @param orgId
   * @throws Exception
   */
  private void updatePlanMaterials(List<AgentPlanDetailVO> detailVOS, String planId, String planNo,
      String orgId) throws Exception {
    agentPlanDetailMapper.deleteByPlanId(planId);
    saveDetails(detailVOS, planId, planNo, orgId);
  }

  @Transactional(rollbackFor = Exception.class)
  public void delete(String planId, String userId) throws Exception {
    AgentPlanDO planDO = agentPlanMapper.getById(planId);
    UserCacheDTO userInfo = commonService.getUserInfo(userId);
    Assert.notNull(userInfo,"userInfo is null");
    if (!planDO.getDeptId().equals(userInfo.getDeptId())) {
      throw new Exception("仅门店内部人员可操作删除");
    }
    if (!AgentPlanStatusEnum.getByStatus(planDO.getStatus()).isCanDelete()) {
      throw new Exception("当前状态不可删除");
    }
    planDO.setDeleteFlag(DELETE_FLAG_YES);
    planDO.setDeleteId(userId);
    planDO.setDeleteName(userInfo.getName());
    planDO.setDeleteTime(new Date());
    agentPlanMapper.update(planDO);

    // 如果删除的是汇总后的采购计划，则释放对应的门店采购计划
    if (planDO.isSummaryPlan()) {
      releaseSummaryedPlan(planDO);
    }
  }

  private void releaseSummaryedPlan(AgentPlanDO planDO) {
    List<AgentPlanDO> agentPlanDOS = agentPlanMapper.listByMergeNo(planDO.getPlanNo(), planDO.getOrgId());
    for (AgentPlanDO agentPlanDO : agentPlanDOS) {
      agentPlanMapper.releaseSummaryedPlan(agentPlanDO.getPlanNo(), planDO.getOrgId());
    }
  }

  @Transactional(readOnly = true)
  public AgentPlanAddVO getSummaryResult(AgentPlanSelectVO selectVO, String userId, String orgId) throws Exception {
    UserCacheDTO userInfo = commonService.getUserInfo(userId);
    if (!isHeadquartersUser(userInfo.getDeptId())) {
      throw new Exception("仅总部人员可汇总采购计划");
    }

    List<AgentPlanVO> planVOS = selectVO.getAgentPlans();
    AgentPlanAddVO addVO = new AgentPlanAddVO();
    AgentPlanVO agentPlanVO = new AgentPlanVO();
    AgentPlanDO agentPlanDO;
    agentPlanDO = agentPlanMapper.getById(planVOS.get(0).getId());
    agentPlanVO.setTypeId(agentPlanDO.getTypeId());
    agentPlanVO.setTypeDesc(agentPlanDO.getTypeDesc());
    agentPlanVO.setPlanType(PLAN_TYPE_SUMMARY);
    agentPlanVO.setGenPurFlag(GEN_PUR_FLAG_NO);
    addVO.setHeaderInfo(agentPlanVO);

    List<String> planNos = new ArrayList<>();

    //统计采购计划类型数量，一次汇总只能有一种类型的采购计划
    Set<Integer> typeIdSet = new HashSet<>();
    Map<String, AgentPlanDetailVO> summaryMap = new HashMap<>();
    for (AgentPlanVO planVO : planVOS) {
      agentPlanDO = agentPlanMapper.getById(planVO.getId());
      planNos.add(agentPlanDO.getPlanNo());
      typeIdSet.add(agentPlanDO.getTypeId());
      List<AgentPlanDetailDO> detailDOS =  agentPlanDetailMapper.listByPlanId(planVO.getId());
      for (AgentPlanDetailDO detailDO : detailDOS) {
        summaryMap = resetDetailInfo(summaryMap, detailDO, orgId);
      }
    }
    if (typeIdSet.size() > 1) {
      throw new Exception("存在不同类型的采购计划，不能汇总");
    }
//    List<AgentPlanDetailVO> detailVOS= summaryMap.entrySet().stream().map(et ->et.getValue()).collect(Collectors
//        .toList());
    addVO.setDetailList(getSummaryList(summaryMap, orgId));
    addVO.setSourcePlanNos(planNos);
    return addVO;
  }

  private List getSummaryList(Map<String, AgentPlanDetailVO> summaryMap, String orgId) {
    List<AgentPlanDetailVO> detailVOS = new ArrayList<>();
    AgentPlanDetailVO detailVO;
    for (Map.Entry<String, AgentPlanDetailVO> entry : summaryMap.entrySet()) {
      String materialsNo = entry.getKey();
      detailVO = entry.getValue();
      detailVO = resetPrice4Show(detailVO);
      detailVO = fillStockInfo(detailVO, orgId, materialsNo);
      detailVOS.add(detailVO);
    }
    return detailVOS;
  }

  /**
   * 重置汇总时重复零件的数量，相同零件数量累加，重新计算总价
   *
   * @param summaryMap
   * @param detailDO
   * @return
   */
  private Map<String, AgentPlanDetailVO> resetDetailInfo(Map<String, AgentPlanDetailVO> summaryMap, AgentPlanDetailDO detailDO, String orgId) {
    AgentPlanDetailVO summaryDetail;
    if (summaryMap.containsKey(detailDO.getMaterialsNo())) {
      summaryDetail = summaryMap.get(detailDO.getMaterialsNo());
      BigDecimal qty = summaryDetail.getQty().add(detailDO.getQty());
      summaryDetail.setQty(qty);
      summaryDetail.setAmount(qty.multiply(detailDO.getPrice()));
      // 统计调整后数量与总价
      if (null != detailDO.getAdjustQty() && BigDecimal.ZERO.compareTo(detailDO.getAdjustQty()) != 0) {
        BigDecimal adjustQty = (null == summaryDetail.getAdjustQty() ? BigDecimal.ZERO : summaryDetail.getAdjustQty())
            .add(detailDO.getAdjustQty());
        summaryDetail.setAdjustQty(adjustQty);
        summaryDetail.setAdjustAmount(adjustQty.multiply(detailDO.getPrice()));
      }
    } else {
      summaryDetail = new AgentPlanDetailVO();
      BeanUtils.copyProperties(detailDO, summaryDetail);
    }

    summaryMap.put(detailDO.getMaterialsNo(), summaryDetail);
    return summaryMap;
  }

  /**
   * 可以汇总采购计划的门店采购计划
   *
   * @param condition
   * @return
   */
  public PageCommonVO list4Summary(SearchCommonVO<AgentPlanVO> condition) {
    PageCommonVO<AgentPlanVO> pageCommonVO = new PageCommonVO<>();
      PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize());

    List<AgentPlanDO> planDOS = agentPlanMapper.list4Summary(condition.getFilters());
    List<AgentPlanVO> planVOS = new ArrayList<>();
    AgentPlanVO planVO;
    for (AgentPlanDO planDO : planDOS) {
      planVO = new AgentPlanVO();
      BeanUtils.copyProperties(planDO, planVO);
      planVOS.add(planVO);
    }
    pageCommonVO.setPageInfo(new PageInfo(planDOS));
    pageCommonVO.setPageInfoList(planVOS);
    return pageCommonVO;
  }

  /**
   * 可以生成采购订单的采购计划
   *orderType :
   * @param condition
   * @return
   */
  public PageCommonVO list4PurchaseRequest(SearchCommonVO<AgentPlanVO> condition) {
    PageCommonVO<AgentPlanVO> pageCommonVO = new PageCommonVO<>();
      PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize());

    List<AgentPlanDO> planDOS = agentPlanMapper.list4PurchaseRequest(condition.getFilters());
    List<AgentPlanVO> planVOS = new ArrayList<>();
    AgentPlanVO planVO;
    for (AgentPlanDO planDO : planDOS) {
      planVO = new AgentPlanVO();
      BeanUtils.copyProperties(planDO, planVO);
      planVOS.add(planVO);
    }
    pageCommonVO.setPageInfo(new PageInfo(planDOS));
    pageCommonVO.setPageInfoList(planVOS);
    return pageCommonVO;
  }


  /**
   * 导出采购计划
   *
   * @param condition
   * @throws Exception
   */
  public void export(AgentPlanVO condition)throws Exception{
    List<AgentPlanDetailDO> detailDOS = new ArrayList<>();
    List<AgentPlanDO> planDOS = agentPlanMapper.list(condition);
    for (AgentPlanDO planDO : planDOS) {
      detailDOS.addAll(agentPlanDetailMapper.listByPlanId(planDO.getId()));
    }
    invokeExport(detailDOS);
  }
  /**
   * 采购计划信息导出
   *
   * @param detailDOS
   * @throws Exception
   */
  private void invokeExport(List<AgentPlanDetailDO> detailDOS) throws Exception {
    String title = "采购计划导出";
    String[] rowsName = new String[]{"序号", "采购计划单号", "零件号", "零件名称", "单位","单价", "数量",
        "调整数量"};
    String comment = "导出的此表格可以修改后，作为模板重新导入系统。"
        + "1.导入时，如果采购计划单号这一列有值，则默认是修改该采购计划下的零件数量，除了调整后数量，其他列不可修改，否则可能出错；如果批量修改，每一行都必须有计划单号"
        + "2.导入时，如果采购计划单号这一列被清空，则默认是新增采购计划，数量以调整后数量为准。零件号与调整后数量为必填，导入的默认为门店采购计划，状态草拟，类型为补库。计划单号这列务必清空";

    List<Object[]> dataList = new ArrayList<>();
    if (ListUtil.isNullOrEmpty(detailDOS)) {
      ExportUtil exportUtil = new ExportUtil(title, rowsName, dataList, comment);
      exportUtil.export(response);
      return;
    }
    Object[] objs;
    for (int i = 0; i < detailDOS.size(); i++) {
      AgentPlanDetailDO e = detailDOS.get(i);
      objs = new Object[rowsName.length];
      objs[0] = i + 1;
      objs[1] = e.getPlanNo();
      objs[2] = e.getMaterialsNo();
      objs[3] = e.getMaterialsDes();
      objs[4] = e.getUnit();
      objs[5] = String.valueOf(DecimalUtil.roundDecimal4Output(e.getPrice()));
      objs[6] = e.getQty();
      objs[7] = e.getAdjustQty();
      dataList.add(objs);
    }
    ExportUtil exportUtil = new ExportUtil(title, rowsName, dataList, comment);
    exportUtil.export(response);
  }

  @Transactional(rollbackFor = Exception.class)
  public FunctionResult importExcel(MultipartFile file, String orgId, String userId) throws Exception {
    FunctionResult result = new FunctionResult();
    Workbook wb;//同时兼容Excel-2003及Excel-2007
    try {
      InputStream in = file.getInputStream();
      wb = new HSSFWorkbook(in);
    } catch (Exception ex) {
      InputStream in = file.getInputStream();
      wb = new XSSFWorkbook(in);
    }
    Sheet sheet = wb.getSheetAt(0);

    int totalRow = sheet.getLastRowNum();
    if (totalRow < 2) {
      result.setCode(ErrorCode.IllegalArument);
      result.setValue("模板错误");
      return result;
    }
    int totalCell = sheet.getRow(2).getLastCellNum();
    if (totalCell != 8) {
      result.setCode(ErrorCode.IllegalArument);
      result.setValue("模板错误");
      return result;
    }

    String newPlanNo = null;
    String newPlanId = null;
    List<AgentPlanDetailVO> planDetailDVS = new ArrayList<>();

    for (int i = 3; i <= totalRow; i++) {
      Row curRow = sheet.getRow(i);
      if (curRow == null) {
        continue;
      }
      String planNo = getCellValue(curRow,1);
      String materialsNo = getCellValue(curRow,2);
      String adjustQty = getCellValue(curRow,7);
      if (StringUtils.isBlank(planNo) || StringUtils.isBlank(materialsNo)) {
        if (StringUtils.isBlank(newPlanNo)) {
          ActionResult<String> textResult = fastGenClient.textGuid();
          newPlanId = textResult.getValue();
          newPlanNo = genDocumentService.genDocumentNo(BillDesc.AgentPlan, orgId);
          save4Import(newPlanId, newPlanNo, orgId, userId);
        }
        AgentPlanDetailVO detailVO = new AgentPlanDetailVO();
        detailVO.setPlanId(newPlanId);
        detailVO.setPlanNo(newPlanNo);
        detailVO.setMaterialsNo(materialsNo);
        detailVO.setQty(new BigDecimal(adjustQty));
        detailVO.setAdjustQty(new BigDecimal(adjustQty));
        planDetailDVS.add(detailVO);
        continue;
      }
      AgentPlanDO agentPlanDO = agentPlanMapper.getByPlanNo(planNo, orgId);
      if (null == agentPlanDO) {
        result.setCode(ErrorCode.IllegalArument);
        result.setValue("未查询到采购计划：" + planNo);
        return result;
      }

      if (!AgentPlanStatusEnum.getByStatus(agentPlanDO.getStatus()).isCanUpdate()) {
        result.setCode(ErrorCode.IllegalArument);
        result.setValue("当前状态不可修改。单号：" + agentPlanDO.getPlanNo());
        return result;
      }

      UserCacheDTO userInfo = commonService.getUserInfo(userId);
      if (!agentPlanDO.getDeptId().equals(userInfo.getDeptId())) {
        result.setCode(ErrorCode.IllegalArument);
        result.setValue("仅门店内部人员可修改");
        return result;
      }

      if (StringUtils.isBlank(adjustQty)) {
        result.setCode(ErrorCode.IllegalArument);
        result.setValue("调整后数量不能为空。单号：" + planNo + "，零件号：" + materialsNo);
        return result;
      }
      BigDecimal adjustQtyVal = new BigDecimal(adjustQty);
      if (BigDecimal.ZERO.compareTo(adjustQtyVal) == 0) {
        result.setCode(ErrorCode.IllegalArument);
        result.setValue("调整后数量不能为0，单号：" + planNo + ", 零件号：" + materialsNo);
        return result;
      }

      AgentPlanDetailDO detailDO = agentPlanDetailMapper.getByMaterialsNo(planNo, materialsNo);
      if (null == detailDO) {
        result.setCode(ErrorCode.IllegalArument);
        result.setValue("采购单" + planNo + "未查询到零件：" + materialsNo);
        return result;
      }
      detailDO.setAdjustQty(adjustQtyVal);
      detailDO.setAdjustAmount(adjustQtyVal.multiply(detailDO.getPrice()));
      agentPlanDetailMapper.updateByMaterialsNo(detailDO);
    }

    if (!CollectionUtils.isEmpty(planDetailDVS)) {
      saveDetails(planDetailDVS, newPlanId, newPlanNo, orgId);
    }

    result.setCode(ErrorCode.Success);
    result.setValue(ErrorCode.Success.getDesc());
    return result;
  }


  private String getCellValue(Row curRow, int i){
    Cell cell = curRow.getCell(i);
    if (null == cell) {
      return StringUtils.EMPTY;
    }
    cell.setCellType(CellType.STRING);
    return StringUtils.trim(cell.getStringCellValue());
  }

  private Integer save4Import(String panId, String planNo, String orgId, String userId)
      throws Exception {
    AgentPlanDO agentPlanDO = new AgentPlanDO();
    agentPlanDO.setId(panId);
    agentPlanDO.setPlanNo(planNo);
    agentPlanDO.setTypeId(AGENT_PLAN_TYPE_ID_BK);
    agentPlanDO.setTypeDesc(getPurchaseDesc(AGENT_PLAN_TYPE_ID_BK));
    agentPlanDO.setPlanType(PLAN_TYPE_STORE);
    agentPlanDO.setStatus(AgentPlanStatusEnum.DRAFT.getStatus());
    agentPlanDO.setDeleteFlag(DELETE_FLAG_NO);
    agentPlanDO.setOrgId(orgId);

    UserCacheDTO userInfo = commonService.getUserInfo(userId);
    Assert.notNull(userInfo,"userInfo is null");

    agentPlanDO.setDeptId(userInfo.getDeptId());

    if (null == userInfo.getDeptName() && HEADQUARTERS_PARENT_DEPT_ID.equals(userInfo.getDeptId())) {
      CompanyInfoDO companyInfoDO = companyInfoMapper.item(orgId);
      if (null == companyInfoDO) {
        throw new Exception("未查询到相关公司：" + orgId);
      }
      agentPlanDO.setDeptName(companyInfoDO.getCompanyName());
    } else {
      agentPlanDO.setDeptName(userInfo.getDeptName());
    }
    agentPlanDO.setCreateId(userInfo.getUserId());
    agentPlanDO.setCreateName(userInfo.getName());
    agentPlanDO.setCreateTime(new Date());
    return agentPlanMapper.insert(agentPlanDO);
  }

  /**
   * 生成采购订单时选择采购计划
   * @param planId
   * @return
   */
  public AgentPlanAddVO select4PurchaseOrder(String planId, String orgId,String dealerOrgId) throws Exception {
    if (!StringUtil.isNotEmpty(planId)) {
      return new AgentPlanAddVO();
    }
    AgentPlanDO agentPlanDO = agentPlanMapper.getById(planId);
    if (null == agentPlanDO) {
      throw new Exception("未查到采购计划");
    }
    AgentPlanVO agentPlanVO = new AgentPlanVO();
    BeanUtils.copyProperties(agentPlanDO, agentPlanVO);
    List<AgentPlanDetailDO> detailDOList = agentPlanDetailMapper.listByPlanId(planId);
    List<AgentPlanDetailVO> detailVOList = new ArrayList<>();
    AgentPlanDetailVO detailVO;
    for (AgentPlanDetailDO detailDO : detailDOList) {
      detailDO.setPrice(DecimalUtil.roundDecimal4Output(detailDO.getPrice()));
      detailDO.setAmount(DecimalUtil.roundDecimal4Output(detailDO.getAmount()));
      detailVO = new AgentPlanDetailVO();
      BeanUtils.copyProperties(detailDO, detailVO);
      detailVO = fillDeliveryDate(detailVO, orgId, detailDO.getMaterialsNo());
      setReplaceMaterials(detailVO,dealerOrgId);
      detailVOList.add(detailVO);
    }
    AgentPlanAddVO result = new AgentPlanAddVO();
    result.setHeaderInfo(agentPlanVO);
    result.setDetailList(detailVOList);
    return result;
  }

  private void setReplaceMaterials(AgentPlanDetailVO detailVO, String dealerOrgId) {
    if (!StringUtil.isNotEmpty(dealerOrgId)) {
      return;
    }

    PriMaterialsDO priMaterialsDO = priMaterialsMapper.itemByNo(detailVO.getMaterialsNo(), dealerOrgId);
    if (priMaterialsDO == null) {
      return;
    }

//    Set<String> replaceNo = new HashSet<>();
//    Set<String> replaceDes = new HashSet<>();
//    getPriMaterialsDO(priMaterialsDO, replaceNo, replaceDes);
    detailVO.setReplaceMaterialsNo(priMaterialsDO.getReplaceMaterialsNo());
    detailVO.setReplaceMaterialsDes(priMaterialsDO.getReplaceMaterialsNote());
    detailVO.setReplaceMaterialsNote(priMaterialsDO.getReplaceMaterialsNote());
  }

  private void getPriMaterialsDO(PriMaterialsDO replaceDo, Set<String> replaceNo, Set<String> replaceDes) {
    if (null == replaceDo) {
      return;
    }

    String[] arrReplaceMaterialsNo = replaceDo.getReplaceMaterialsNo().split(",");
    for (String replaceMaterialsNo : arrReplaceMaterialsNo) {
      int repInt = 0;
      PriMaterialsDO replace = replaceDo;
      if (replaceMaterialsNo.equals(replaceDo.getMaterialsNo())) {
        replaceNo.add(replaceDo.getMaterialsNo());
        replaceDes.add(replaceDo.getMaterialsDes());
        continue;
      }
      replaceDo = priMaterialsMapper.itemByNo(replaceMaterialsNo, replaceDo.getOrgId());
      if (null == replaceDo) {
        replaceNo.add(replace.getMaterialsNo());
        replaceDes.add(replace.getMaterialsDes());
        continue;
      }
      if (StringUtils.isBlank(replaceDo.getReplaceMaterialsNo())) {
        replaceNo.add(replaceDo.getMaterialsNo());
        replaceDes.add(replaceDo.getMaterialsDes());
        continue;
      }
      getPriMaterialsNO(replaceDo, replaceNo, replaceDes, repInt);
    }
  }

  private void getPriMaterialsNO(PriMaterialsDO replaceDo, Set<String> replaceNo, Set<String> replaceDes, int repInt) {
    if (null == replaceDo) {
      return;
    }
    String[] arrReplaceMaterialsNo = replaceDo.getReplaceMaterialsNo().split(",");
    for (String replaceMaterialsNo : arrReplaceMaterialsNo) {
      if (repInt > 20) {
        replaceNo.add(replaceDo.getMaterialsNo());
        replaceDes.add(replaceDo.getMaterialsDes());
        continue;
      }
      repInt++;
      PriMaterialsDO replace = replaceDo;
      if (replaceMaterialsNo.equals(replaceDo.getMaterialsNo())) {
        replaceNo.add(replaceDo.getMaterialsNo());
        replaceDes.add(replaceDo.getMaterialsDes());
        continue;
      }
      replaceDo = priMaterialsMapper.itemByNo(replaceMaterialsNo, replaceDo.getOrgId());
      if (null == replaceDo) {
        replaceNo.add(replace.getMaterialsNo());
        replaceDes.add(replace.getMaterialsDes());
        continue;
      }
      if (StringUtils.isBlank(replaceDo.getReplaceMaterialsNo())) {
        replaceNo.add(replaceDo.getMaterialsNo());
        replaceDes.add(replaceDo.getMaterialsDes());
        continue;
      }
      getPriMaterialsNO(replaceDo, replaceNo, replaceDes, repInt);
    }
  }

  /**
   * 填充库存相关信息
   *
   * @param detailVO
   * @param orgId
   * @param materialsNo
   * @return
   */
  private AgentPlanDetailVO fillStockInfo(AgentPlanDetailVO detailVO, String orgId, String materialsNo) {
    detailVO.setStock(warehouseInventoryMapper.countStock(materialsNo, orgId));
    detailVO.setTransitStock(purchaseRequestDetailMapper.countTransitStock(orgId, materialsNo));
    MaterialsSafetyStock safetyStock = materialsSafetyStockMapper.getByMaterialsNo(orgId, materialsNo);
    if (null == safetyStock) {
      return detailVO;
    }
    detailVO.setUpperLimitStock(safetyStock.getUpperLimitStock());
    return detailVO;
  }

  /**
   * 填充交货日期信息
   *
   * @param detailVO
   * @param orgId
   * @param materialsNo
   * @return
   */
  private AgentPlanDetailVO fillDeliveryDate(AgentPlanDetailVO detailVO, String orgId, String materialsNo) {
    MaterialsSafetyStock safetyStock = materialsSafetyStockMapper.getByMaterialsNo(orgId, materialsNo);
    if (null == safetyStock) {
      return detailVO;
    }
    if (null != safetyStock.getDeliverySpend()) {
      // 取出的单位是月，换算成天
      BigDecimal deliverySpend = new BigDecimal("30").multiply(safetyStock.getDeliverySpend()).setScale(0, BigDecimal.ROUND_HALF_UP);
      detailVO.setDeliveryDate(DateUtil.calNewDate(new Date(), deliverySpend.intValue()));
    }
    return detailVO;
  }

}
